#include <stdio.h>
#include "link.h"
#include <sys/types.h>
#include <dirent.h>
#include "player.h"
#include <dirent.h>
#include "main.h"
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/ioctl.h>

#include <alsa/asoundlib.h>


extern Node* head;

int shmid;
shm *shmaddr;

int g_start_flag=0;                     //表示没有开始播放音乐
int g_suspend_flag=0;                   //表示没有暂停

long new_vol_left,new_vol_right;        //最新的音量

int InitShm()
{
        //生成一个唯一的 System V IPC（Inter-Process Communication，进程间通信）键值
        key_t key = ftok(".", 65);
        if (key == -1) {
                perror("ftok");
                exit(1);
        }
        shmid = shmget(key, sizeof(shm), 0666 | IPC_CREAT);
       
        if(shmid==-1){
                return FAILURE;
        }

        // 将共享内存连接到当前进程的地址空间
        shmaddr = (struct shm *)shmat(shmid, NULL, 0);
        if ((void *)shmaddr == (void *)(-1)) {
                perror("shmat");
                exit(1);
        }

        //初始化共享内存数据
        shmaddr->play_mode=SEQUENCEMODE;
        shmaddr->ppid=getpid();

        return SUCCESS;
}

//判断是否是.mp3结尾
int m_mp3_end(const char* name){
        const char* ptr=name;
        while(*ptr!='\0'){
                ptr++;
        }
        int i;
        for(i=0;i<4;i++){
                ptr--;
        }
        if(ptr<name){
                return 0;
        }
        return (strcmp(ptr,".mp3")==0)?1:0;
}

//打开目录，获得音乐文件
void getMusic(){
        //打开目录
        DIR* dir=opendir(MUSIC_PATH);
        if(dir==NULL){
                perror("opendir");
                exit(-1);
        }
        //读取目录
        struct dirent *file=NULL;
        while((file=readdir(dir))!=NULL)
        {
                if(file->d_type != 8){       //不是普通文件
                        continue;
                }
                if(!m_mp3_end(file->d_name)){   //不是mp3文件
                        continue;
                }
                printf("%s\n",file->d_name);

                int ret=insertLink(head,file->d_name);
                if(ret==FAILURE){
                        printf("歌曲插入失败\n");
                        exit(-1);
                }

        }


}

//播放音乐
void play_music(const char* name)
{
        pid_t child_pid=fork();
        if(child_pid==-1){
                perror("fork");
                exit(-1);
        }
        else if(child_pid==0)           //子进程
        {                  
                
                while(1){
                        pid_t grand_pid=fork();
                        if(grand_pid==-1){
                                perror("fork");
                                exit(-1);
                        }
                        else if(grand_pid==0){                  //孙进程
                                char cur_name[64]={0};
                
                                if(strlen(name)!=0){            //直接开始播放
                                        strcpy(cur_name,name);
                                        
                                }
                                else
                                {                        
                                        //判断播放模式，找到下一首歌曲 
                                        findNextMusic(shmaddr->cur_name,shmaddr->play_mode,cur_name);     
                                }
                                
                                //写一些数据到共享内存里（父子孙进程号，当前播放的歌曲名，）

                                //strcpy(shmaddr->cur_name,name);
                                strcpy(shmaddr->cur_name,cur_name);
                                shmaddr->child_pid=getppid();
                                shmaddr->grand_pid=getpid();

                                //播放音乐
                                char music_path[128]={0};
                                strcpy(music_path,MUSIC_PATH);
                                strcat(music_path,cur_name);
                                printf("歌曲名：%s\n",music_path);

                                execl("/bin/madplay", "madplay", music_path, NULL);  
                        }
                        else                                            //子进程
                        {                                   
                                memset((void *)name,0,strlen(name));    //歌曲名长度变为0,方便下一次操作
                                int status;                     
                                waitpid(grand_pid,&status,0);   //阻塞方式等待回收孙进程
                        }
                }                
                
        }
        else
        {
                return;
        }
        
}

void start_play()
{
        if(g_start_flag==1){            //已经开始播放
                return;
        }
        //获取歌曲名
        if(head->next==NULL){           //没有歌曲
                return;
        }

        snd_mixer_t *handle=NULL;
        snd_mixer_selem_id_t *sid;
        const char *soundCardName = "hw:0";
        const char *selem_name = "PCM"; // 可能需要根据系统进行调整

        int ret;

        //打开混音器
        ret=snd_mixer_open(&handle, 0);
        if(ret<0){
                fprintf(stderr, "snd_mixer_open error: %s\n", snd_strerror(ret));
        }
        //关联声卡控制设备
        ret=snd_mixer_attach(handle, soundCardName);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_attach error: %s\n", snd_strerror(ret));
        }
        //注册混音器
        ret=snd_mixer_selem_register(handle, NULL, NULL);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_selem_register error: %s\n", snd_strerror(ret));
        }
        //加载混音器
        ret=snd_mixer_load(handle);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_load error: %s\n", snd_strerror(ret));
        } 
        //分配并返回一个snd_mixer_selem_id 结构体的指针。这个结构体用于标识音频混音器中的一个控制元素（如音量、平衡等）
        snd_mixer_selem_id_alloca(&sid);
        
        snd_mixer_selem_id_set_name(sid, selem_name);
        //在指定的混音器中查找具有特定标识符的控制元素
        snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);

        if (elem) {
                long min, max;
                snd_mixer_selem_get_playback_volume_range(elem, &min, &max);

                new_vol_left = min + (max - min) / 10;
                new_vol_right = min + (max - min) / 10;

                snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, new_vol_left);
                snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, new_vol_right);

                printf("最初音量设为10%%成功\n");
        } else {
                printf("最初音量设为10%%失败\n");
        }

        snd_mixer_close(handle);

        char name[128]={0};
        strcpy(name,head->next->music_name);
        
        play_music(name);
        g_start_flag=1;
}

void stop_play()
{
        if(g_start_flag==0){
                return;
        }
        kill(shmaddr->child_pid,SIGKILL);
        kill(shmaddr->grand_pid,SIGKILL);
        g_start_flag=0;

}

void suspend_play()
{
        if(g_start_flag==0 || g_suspend_flag==1){
                return;
        }
        kill(shmaddr->child_pid,SIGSTOP);
        kill(shmaddr->grand_pid,SIGSTOP);
        g_suspend_flag=1;
        

}
void continue_play()
{
        if(g_start_flag==0 || g_suspend_flag==0){
                return;
        }
        kill(shmaddr->child_pid,SIGCONT);
        kill(shmaddr->grand_pid,SIGCONT);
        g_suspend_flag=0;
}
//设计的只有正在播放时才能切换上一首
void prior_play()
{
        if(g_start_flag==0 || g_suspend_flag==1){
                return;
        }
        kill(shmaddr->child_pid,SIGKILL);
        kill(shmaddr->grand_pid,SIGKILL);
        g_start_flag=0;

        char name[64]={0};
        PriorMusic(shmaddr->cur_name,shmaddr->play_mode,name);
        play_music(name);
        g_start_flag=1;

}
//设计的只有正在播放时才能切换下一首
void next_play()
{
        if(g_start_flag==0 || g_suspend_flag==1){
                return;
        }
        kill(shmaddr->child_pid,SIGKILL);
        kill(shmaddr->grand_pid,SIGKILL);
        g_start_flag=0;

        char name[64]={0};
        NextMusic(shmaddr->cur_name,shmaddr->play_mode,name);
        play_music(name);
        g_start_flag=1;
}



void voice_up()
{
        snd_mixer_t *handle=NULL;
        snd_mixer_selem_id_t *sid;
        const char *soundCardName = "hw:0";
        const char *selem_name = "PCM"; // 可能需要根据系统进行调整

        int ret;
        
        //打开混音器
        ret=snd_mixer_open(&handle, 0);
        if(ret<0){
                fprintf(stderr, "snd_mixer_open error: %s\n", snd_strerror(ret));
        }
        //关联声卡控制设备
        ret=snd_mixer_attach(handle, soundCardName);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_attach error: %s\n", snd_strerror(ret));
        }
        //注册混音器
        ret=snd_mixer_selem_register(handle, NULL, NULL);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_selem_register error: %s\n", snd_strerror(ret));
        }
        //加载混音器
        ret=snd_mixer_load(handle);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_load error: %s\n", snd_strerror(ret));
        } 
        //分配并返回一个 snd_mixer_selem_id 结构体的指针。这个结构体用于标识音频混音器中的一个控制元素（如音量、平衡等）
        snd_mixer_selem_id_alloca(&sid);
        
        snd_mixer_selem_id_set_name(sid, selem_name);
        //在指定的混音器中查找具有特定标识符的控制元素
        snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);

        if (elem) {
                
                long min, max;
                snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
                
                // Increase volume by 10%
                long current_vol_left, current_vol_right;
                
                snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &current_vol_left);
                snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &current_vol_right);
                
                new_vol_left = current_vol_left + (max - min) / 10; // Increase by 10%
                new_vol_right = current_vol_right + (max - min) / 10; // Increase by 10%

                snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, new_vol_left);
                snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, new_vol_right);

                printf("Volume increased by 10%%\n");
        } else {
                printf("Unable to find the mixer element\n");
        }

        snd_mixer_close(handle);

}

void voice_down()
{
        snd_mixer_t *handle=NULL;
        snd_mixer_selem_id_t *sid;
        const char *soundCardName = "hw:0";
        const char *selem_name = "PCM"; // 可能需要根据系统进行调整

        int ret;

        //打开混音器
        ret=snd_mixer_open(&handle, 0);
        if(ret<0){
                fprintf(stderr, "snd_mixer_open error: %s\n", snd_strerror(ret));
        }
        //关联声卡控制设备
        ret=snd_mixer_attach(handle, soundCardName);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_attach error: %s\n", snd_strerror(ret));
        }
        //注册混音器
        ret=snd_mixer_selem_register(handle, NULL, NULL);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_selem_register error: %s\n", snd_strerror(ret));
        }
        //加载混音器
        ret=snd_mixer_load(handle);
        if (0 > ret){
                fprintf(stderr, "snd_mixer_load error: %s\n", snd_strerror(ret));
        } 
        //分配并返回一个 snd_mixer_selem_id 结构体的指针。这个结构体用于标识音频混音器中的一个控制元素（如音量、平衡等）
        snd_mixer_selem_id_alloca(&sid);
        
        snd_mixer_selem_id_set_name(sid, selem_name);
        //在指定的混音器中查找具有特定标识符的控制元素
        snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);

        if (elem) {
                
                long min, max;
                snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
                
                // Decrease volume by 10%
                long current_vol_left, current_vol_right;
                
                snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &current_vol_left);
                snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &current_vol_right);
                
                new_vol_left = current_vol_left - (max - min) / 10; // Increase by 10%
                new_vol_right = current_vol_right - (max - min) / 10; // Increase by 10%

                snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, new_vol_left);
                snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, new_vol_right);

                printf("Volume decreased by 10%%\n");
        } else {
                printf("Unable to find the mixer element\n");
        }

        snd_mixer_close(handle);
}

void set_mode(int mode)
{
        shmaddr->play_mode=mode;
        printf("模式修改成功\n");
}